package cn.turboinfo.fuyang.api.gateway.admin.controller.role;

import cn.turboinfo.fuyang.api.domain.admin.service.menu.MenuService;
import cn.turboinfo.fuyang.api.domain.admin.usecase.role.AdminListRoleCheckablePermissionUseCase;
import cn.turboinfo.fuyang.api.domain.common.service.role.RolePermissionService;
import cn.turboinfo.fuyang.api.domain.common.service.role.RoleService;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.Role;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.RoleCreator;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.RoleUpdater;
import cn.turboinfo.fuyang.api.gateway.admin.fo.role.RoleAssignPermissionFO;
import cn.turboinfo.fuyang.api.gateway.admin.fo.role.RoleCreateFO;
import cn.turboinfo.fuyang.api.gateway.admin.fo.role.RoleUpdateFO;
import cn.turboinfo.fuyang.api.gateway.admin.framework.http.ResponseBodyWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Controller
@ResponseBodyWrapper
@RequestMapping(value = "/admin/role")
public class RoleController {

    private final RoleService roleService;

    private final MenuService menuService;

    private final RolePermissionService rolePermissionService;

    private final AdminListRoleCheckablePermissionUseCase listRoleCheckablePermissionUseCase;

    @RequiresPermissions("adminRole:list")
    @GetMapping("/checkAvailable")
    public boolean checkAvailable(@RequestParam String code, @RequestParam(required = false, defaultValue = "0") Long id) {
        if (id != null && id > 0) {
            Optional<Role> roleOptional = roleService.getById(id);
            if (roleOptional.isPresent()) {
                Role role = roleOptional.get();
                if (role.getCode().equals(code)) {
                    // 可以维持使用自身的不做变动
                    return true;
                }
            } else {
                return false;
            }
        }
        return roleService.getByCode(code).isEmpty();
    }

    @RequiresPermissions("adminRole:list")
    @GetMapping("/list")
    public Collection<Role> list() {
        return roleService.findAll();
    }

    @RequiresPermissions("adminRole:create")
    @PostMapping("/create")
    public Role create(@RequestBody @Valid RoleCreateFO fo) {
        RoleCreator.Builder builder = RoleCreator.builder();
        QBeanCreatorHelper.copyPropertiesToCreatorBuilder(builder, RoleCreator.class, fo);
        return roleService.save(builder.build());
    }

    @RequiresPermissions("adminRole:update")
    @PostMapping("/update")
    public Role update(@RequestBody @Valid RoleUpdateFO fo) {
        RoleUpdater.Builder builder = RoleUpdater.builder(fo.getId());
        QBeanUpdaterHelper.copyPropertiesToUpdateBuilder(builder, RoleUpdater.class, fo);
        return roleService.update(builder.build());
    }

    @RequiresPermissions("adminRole:delete")
    @PostMapping("/delete")
    public void delete(@RequestParam Long id) {
        roleService.deleteById(id);
    }

    @RequiresPermissions("adminRole:assignPermission")
    @GetMapping("/checkablePermissionList")
    public AdminListRoleCheckablePermissionUseCase.OutputData checkablePermissionList(@RequestParam Long id) {
        return listRoleCheckablePermissionUseCase.execute(AdminListRoleCheckablePermissionUseCase.InputData
                .builder()
                .roleId(id)
                .build());
    }

    @RequiresPermissions("adminRole:assignPermission")
    @PostMapping("/assignPermission")
    public void assignPermission(@RequestBody @Valid RoleAssignPermissionFO fo) {
        roleService.getByIdEnsure(fo.getRoleId());

        List<Long> permissionIdList = new ArrayList<>();
        if (fo.getCheckedPermissionIds() != null) {
            permissionIdList.addAll(Arrays.asList(fo.getCheckedPermissionIds()));
        }
        if (fo.getHalfCheckedPermissionIds() != null) {
            permissionIdList.addAll(Arrays.asList(fo.getHalfCheckedPermissionIds()));
        }
        rolePermissionService.reassign(fo.getRoleId(), permissionIdList);
    }
}
